﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Jurassic;
using Jurassic.Library;
using System.IO;
namespace SGUI
{
    public class UIManager    
    {
        public static AtlasManager Atlas;
        public static EventManager Event;
        static Dictionary<string, SGUIFont> mFonts = new Dictionary<string,SGUIFont>();
        public static RootView RootNode;
        public static ScriptEngine JsEngine;
        public static Dictionary<string, ASTTree> SGMlComponents; 

        public static SGUIFont DefaultFont
        {
            get
            {
                if (mFonts.ContainsKey("default"))
                {
                    return mFonts["default"];
                }
                else
                {
                    return null;  
                }
            }
        }

        public static void Init(string fontPath,string atlasPath,float viewSize = 1080f)  
        {
            Font font = (Font)Resources.Load(fontPath);
            SGUIFont uiFont = new SGUIFont();
            uiFont.font = font;
            mFonts["default"] = uiFont;
            GameObject go = new GameObject("Root");
        
            RootNode = go.AddComponent<RootView>();
            RootNode.ViewSize = viewSize;    
            RootNode.Init();
            RootNode.OnEnter();
            
            Atlas = new AtlasManager();
            Event = new EventManager();
            JsEngine = new ScriptEngine();
            JsEngine.SetGlobalFunction("log", new System.Action<string>(DebugLog));
            JsEngine.SetGlobalFunction("SetComponenProperty", new System.Action<string, string,object>(UIManager.SetComponenProperty));
            JsEngine.SetGlobalFunction("GetComponenProperty", new System.Func<string, string,object>(UIManager.GetComponenProperty));

            LoadSGMLComponents();
        }
        static  public void DebugLog(string str)
        {
            Debug.Log(str);
        }
        static void LoadSGMLComponents()  
        {
            SGMlComponents = new Dictionary<string, ASTTree>();
            string SGMlPath = Application.streamingAssetsPath + "/SGML/";
            DirectoryInfo sgmlInfo = new DirectoryInfo(SGMlPath);
            FileInfo[] files = sgmlInfo.GetFiles();
            for (int i = 0; i < files.Length;i++)
            {
                if (files[i].Extension == ".txt") 
                {
                   string ComponentName = files[i].Name.Split('.')[0];
                   string SGMLTxt = File.OpenText(files[i].FullName).ReadToEnd();
                   ASTTree tree = ASTTree.ParseString(ComponentName,SGMLTxt);
                   SGMlComponents.Add(ComponentName, tree);
                }
            }
        }
        public static void CreateComponent(string sgmlName,SGComponent parentNode = null) 
        {
            if (parentNode == null) 
            {
                parentNode = RootNode;
            }
            StreamReader sr =  File.OpenText(Application.streamingAssetsPath+"/SGML/"+sgmlName+".txt");
            if (sr == null) return;
            ASTTree tree = ASTTree.ParseString(sgmlName, sr.ReadToEnd());
            ASTNode rootNode = tree.Roots[0];
            if (rootNode.NodeType == ASTNode.ASTNodeType.ComponentNode) 
            {
                visitComponent((ComponentNode)rootNode, parentNode);              
            }
            CallOnLoadEvent(parentNode);
        }

        static void CallOnLoadEvent(SGComponent node) 
        {
            if (node != null && node.Children != null)
            {
                for (int i = 0; i < node.Children.Count; i++)
                {
                    CallOnLoadEvent(node.Children[i]);
                }
                node.OnLoad();
            }
        }
        static void visitComponent(ComponentNode node,SGComponent parent) 
        {

            GameObject go = new GameObject(node.ComponentName);
            SGComponent Component = null;
            ComponentNode useComponentNode = null; 
            if (SGMlComponents.ContainsKey(node.ComponentName)) 
            {
                ComponentNode rootNode = (ComponentNode)SGMlComponents[node.ComponentName].Roots[0];
                Component = (SGComponent)go.AddComponent(rootNode.ComponentName);
                useComponentNode = node;
                node = rootNode;
            }
            else 
            {
                Component = (SGComponent)go.AddComponent(node.ComponentName);
            }

            Component.Init();
            if (parent != null)
            {
                parent.AddChildren(Component);
            }
            //先添加自定义属性
            for (int i = 0; i < node.nodes.Count; i++)
            {
                if (node.nodes[i].NodeType == ASTNode.ASTNodeType.DefinePropertyNode) 
                {
                    DefinePropertyNode defattr = (DefinePropertyNode)node.nodes[i];
                    Component.AddProperty(defattr.PropertyName,defattr.DefaultValue); ;
                }
            }
            //在给属性赋值.
            for (int i = 0; i < node.nodes.Count;i++) 
            {
                if (node.nodes[i].NodeType == ASTNode.ASTNodeType.AttributeNode) 
                {
                    AttributeNode attrNode = (AttributeNode)node.nodes[i];
                    //如果是变量类型
                    if (attrNode.ValueNode.NodeType == ASTNode.ASTNodeType.SymbolNode)
                    {
                        SymbolNode symNode = (SymbolNode)attrNode.ValueNode;
                        if (symNode.Val[0] == '$')
                        {
                            string[] uiModelStrInfoArr = symNode.Val.Substring(1, symNode.Val.Length - 1).Split('.');
                            UIModel uimodel =  UIModelManager.Get(uiModelStrInfoArr[0]);
                            Property modelProperty = uimodel.GetProperty(uiModelStrInfoArr[1]);
                            Property curProperty = Component.GetProperty(attrNode.AttrName);
                            curProperty.Binding(modelProperty, Property.BindingType.OneWay);
                            Component.SetProperty(attrNode.AttrName, modelProperty.Value, false);
                        }
                        else 
                        {
                            Property symProperty = Component.FindProperty(symNode.Val);
                            Property curProperty = Component.GetProperty(attrNode.AttrName);
                            curProperty.Binding(symProperty, Property.BindingType.OneWay);
                            Component.SetProperty(attrNode.AttrName, symProperty.Value, false);
                        }
                    }
                    else
                    {
                        Component.SetProperty(attrNode.AttrName, attrNode.ValueNode.GetValue(), false);
                    }
                }
            }
            //如果是自定义组件设置属性.
            if (useComponentNode != null) 
            {
                for (int i = 0; i < useComponentNode.nodes.Count; i++)
                {
                    if (useComponentNode.nodes[i].NodeType == ASTNode.ASTNodeType.AttributeNode)
                    {
                        AttributeNode attrNode = (AttributeNode)useComponentNode.nodes[i];
                        if (attrNode.ValueNode.NodeType == ASTNode.ASTNodeType.SymbolNode)
                        {
                            SymbolNode symNode = (SymbolNode)attrNode.ValueNode;
                            Component.SetProperty(attrNode.AttrName, Component.FindProperty(symNode.Val).Value);
                        }
                        else
                        {
                            Component.SetProperty(attrNode.AttrName, attrNode.ValueNode.GetValue());
                        }
                    }
                }
            }
            //创建子元素.
            for (int i = 0; i < node.nodes.Count;i++) 
            {
                if (node.nodes[i].NodeType == ASTNode.ASTNodeType.ComponentNode)
                {
                    visitComponent((ComponentNode)node.nodes[i], Component);
                }
            }
            Component.GenScript();
            Component.OnEnter();
        }

        public static void SetComponenProperty(string id,string k,object value)  
        {
            UIManager.RootNode.GetComponentById(id).SetProperty(k,value);
        }
        public static object GetComponenProperty(string id,string k) 
        {
            return UIManager.RootNode.GetComponentById(id).GetProperty(k).Value;
        }



    }
}
